package cn.asura.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


public class Server {
    private ServerSocket server;            //与用户连接的socket套接字
    private Map<String, PrintWriter> pws;    //用户名字为唯一标识符，与对应的输出流做映射关系

    /*初始化socket和Map*/
    public Server() {
        try {
            server = new ServerSocket(8091);
            pws = new HashMap<>();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*存储用户名字-输出流映射*/
    public void savePw(String name, PrintWriter pw) {
        if (pw == null) {
            return;
        }
        pws.put(name, pw);
    }

    /*向全部用户发送数据*/
    public void sendToAll(String msg) {
        if (msg == null || msg.trim().length() == 0) {
            return;
        }
        Set<String> names = pws.keySet();    //获取用户名字集
        for (String name : names) {               //遍历名字集，获取对应的用户输出流发送数据
            PrintWriter pw = pws.get(name);
            pw.println(msg);
        }
    }

    //私信功能，server接受到的格式为senderName:@receiverName:msg
    public boolean sendToOne(String msg) {
        if (!msg.contains("@")) {
            return false;
        }
        if ((!msg.contains(":")) && (!msg.contains("；"))) {
            return false;
        }
        System.out.println(msg);
        String[] arr = msg.split(":");  //获取到["sender","@receiver","msg"]
        String senderName = arr[0];
        String receiverName = arr[1].substring(1);
        StringBuilder message = new StringBuilder();
        for (int i = 2; i < arr.length; i++) {    //msg中可能存在':'
            message.append(arr[i]);
        }
        if (!pws.containsKey(receiverName)) {    //判断receiverName是否上线了
            return false;
        }
        PrintWriter pw1 = pws.get(receiverName);
        pw1.println(senderName + "@了你：" + message.toString());
        PrintWriter pw2 = pws.get(senderName);
        pw2.println("你@了" + receiverName + ":" + message.toString());
        return true;
    }

    /*处理用户信息包括作为中转站的接受用户信息，和再转发给对应用户。这个过程是不断发生的，因此应该是一个进程*/
    class getClientMessageHandler implements Runnable {
        private final Socket socket;

        public getClientMessageHandler(Socket socket) {
            this.socket = socket;
        }

        public void run() {
            String name = null;
            try {
                InputStream is = socket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
                OutputStream os = socket.getOutputStream();
                PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8), true);
                name = br.readLine();        //客户端一上线就先发送了名字
                savePw(name, pw);
                sendToAll(name + "上线了");
                String line;
                while ((line = br.readLine()) != null) {
                    if (!sendToOne(line)) {        //判断是群发还是私信
                        sendToAll(line);
                    }
                }
            } catch (Exception e) {
                sendToAll(name + "下线了");
            }
        }
    }

    public void start() {
        try {
            while (true) {
                System.out.println("等待客户端连接");
                Socket socket = server.accept();
                System.out.println("一个客户端连接");
                Runnable r = new getClientMessageHandler(socket);
                Thread t = new Thread(r);
                t.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        Server server = new Server();
        server.start();
    }
}

